<template>
  <!-- 增改角色弹框 -->
  <hcDialog
    dialogWidth="600px"
    :dialogTitle="options.type === 'add' ? '新增角色' : '编辑角色'"
    customClass="hymson-dialog role-dialog"
    :isVisable="options.show"
    :isFooter="true"
    @closeDialog="closeFun"
    @save="saveDialog(formRef)"
  >
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="22%"
      class="add-role-ruleForm"
      status-icon
    >
      <el-form-item label="角色名称" prop="roleName">
        <el-input v-model="form.roleName" placeholder="请输入角色名称" />
      </el-form-item>
      <el-form-item label="角色编码" prop="roleCode">
        <el-input v-model="form.roleCode" placeholder="请输入角色编码" />
      </el-form-item>
      <el-form-item label="角色顺序" prop="orderNum">
        <el-input-number
          v-model="form.orderNum"
          controls-position="right"
          :min="0"
        />
      </el-form-item>
      <el-form-item label="状态">
        <el-radio-group v-model="form.state">
          <el-radio :label="true">正常</el-radio>
          <el-radio :label="false">停用</el-radio>
        </el-radio-group>
      </el-form-item>
      <el-form-item label="菜单权限">
        <div class="select-menu">
          <el-checkbox
            v-model="selectAll"
            @change="handlerSelectAll"
            label="all"
            size="large"
            >全选</el-checkbox
          >
          <el-tree
            :props="treeProps"
            :data="list"
            ref="treeRef"
            node-key="id"
            default-expand-all
            show-checkbox
            :default-checked-keys="defaultChecked"
            @check-change="handlerChange"
            :check-strictly="true"
          />
        </div>
      </el-form-item>
      <el-form-item label="备注" prop="remark">
        <el-input
          type="textarea"
          v-model="form.remark"
          placeholder="请输入备注"
        />
      </el-form-item>
    </el-form>
  </hcDialog>
</template>

<script setup name="RoleDialog">
import { reactive, ref, toRefs, watch, nextTick } from "vue";
import useTable from "@/hooks/useTable";
const { list } = useTable("/Menu", false); // false 不要分页
const emit = defineEmits(["onSure", "onCancel"]);

const props = defineProps({
  // 当前角色已选择的菜单
  menus: {
    type: Array,
    default: () => {
      return [];
    },
  },
  options: {
    type: Object,
    default: () => {
      return {
        show: false,
        type: "add", // 用于判断是编辑还是删除 add edit
        curRole: null, // 当前编辑的角色
      };
    },
  },
});

const rules = {
  roleName: [{ required: true, message: "请输入角色名称", trigger: "blur" }],
  roleCode: [{ required: true, message: "请输入角色编码", trigger: "blur" }],
};

const treeProps = {
  label: "menuName",
  children: "children",
};

const formRef = ref();

const treeRef = ref();

const data = reactive({
  form: {
    roleName: "", // 角色名
    roleCode: "", // 角色编码
    orderNum: 0, // 排序
    state: true, // 状态
    menuIds: [], // 菜单权限
    remark: "", // 备注
  },
  selectAll: false, // 全选
  flattenTree: [], // 所有树形菜单平铺的数据，用于全选反选
  defaultChecked: [], // 默认选择
  isChange: false, // 用于是否点击选择过菜单，没点过为false
});

// 全选
const handlerSelectAll = () => {
  if (!data.selectAll) {
    data.form.menuIds = [];
    return;
  }
  data.form.menuIds = data.flattenTree.map((item) => {
    return item.id;
  });
};

// 选择变化
const handlerChange = (item, ischecked) => {
  if (!(data.form.menuIds instanceof Array)) {
    data.form.menuIds = JSON.parse(JSON.stringify(data.defaultChecked));
  }
  data.isChange = true;
  let curChildrens = []; // 当前菜单下所有的子菜单 用于全选反选
  if (item.children?.length) {
    flattenTreeFun(item.children, curChildrens);
  }
  let arr = curChildrens.map((child) => child.id);
  // 当前菜单已选中
  if (ischecked) {
    let addArr = [];
    // 添加当前菜单
    if (!data.form.menuIds?.includes(item.id)) {
      addArr.push(item.id);
    }
    // 添加当前菜单的子菜单
    arr.length &&
      arr.forEach((aItem) => {
        if (!data.form.menuIds?.includes(aItem)) {
          addArr.push(aItem);
        }
      });
    data.form.menuIds = data.form.menuIds.concat(addArr);
  } else {
    data.form.menuIds = data.form.menuIds.filter((menu) => item.id !== menu);
    // 反选当前菜单
    data.form.menuIds = data.form.menuIds.filter((menu) => {
      return !arr.includes(menu);
    });
  }
};

// 平铺树结构
const flattenTreeFun = (options, arr) => {
  // 1.先遍历数组
  options.forEach((item) => {
    arr.push(item);
    if (item.children?.length) {
      flattenTreeFun(item.children, arr);
    }
  });
};

// 添加、修改角色
const saveDialog = async (formEl) => {
  // 没点过树菜单 就用默认选择的菜单
  if (!data.isChange) {
    data.form.menuIds = JSON.parse(JSON.stringify(data.defaultChecked));
  }
  if (!formEl) return;
  await formEl.validate((valid) => {
    if (valid) {
      emit("onSure", {
        form: JSON.parse(JSON.stringify(data.form)),
        type: props.options.type,
        id: props.options.curRole?.id, // 用于编辑的id
      });
      closeFun();
    }
  });
};

// 关闭弹框
const closeFun = () => {
  formRef.value.resetFields();
  data.form = {
    roleName: "", // 角色名
    roleCode: "", // 角色编码
    orderNum: 0, // 排序
    state: true, // 状态
    menuIds: [], // 菜单权限
    remark: "", // 备注
  };
  data.flattenTree = [];
  data.selectAll = false;
  data.isChange = false;
  emit("onCancel");
};

watch(
  () => props.options,
  (val) => {
    if (val.show) {
      data.isChange = false;
      flattenTreeFun(list.value, data.flattenTree);
    }
    if (val.type === "edit") {
      const curRole = JSON.parse(JSON.stringify(val.curRole));
      for (let key in data.form) {
        data.form[key] = curRole[key];
      }
    }
  },
  { deep: true, immediate: true }
);

watch(
  () => data.form.menuIds,
  (val) => {
    nextTick(() => {
      if (val?.length && val.length === data.flattenTree.length) {
        data.selectAll = true;
      }
      // 给节点打勾
      val && treeRef.value.setCheckedKeys(val);
    });
  },
  { deep: true }
);

watch(
  () => props.menus,
  (val) => {
    if (val?.length) {
      data.defaultChecked = val.map((item) => {
        return item.id;
      });
      if (data.defaultChecked.length === data.flattenTree.length) {
        data.selectAll = true;
      }
    } else {
      data.defaultChecked = [];
    }
  },
  { deep: true }
);

const { form, selectAll, defaultChecked } = toRefs(data);
</script>

<style lang="scss">
.role-dialog.el-dialog {
  .el-dialog__body {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    .select-menu {
      display: flex;
      flex-direction: column;
      width: 100%;
      border: 1px solid #ddd;
      border-radius: 5px;
      padding: 10px;
      .el-tree {
        max-height: 150px;
        overflow: auto;
      }
    }
  }
  .add-role-ruleForm {
    width: 80%;
    .el-form-item__label {
      font-size: 16px;
      font-weight: 600;
    }
  }
}
</style>
